package com.colorlight.cloud.gateway.api.message.interceptor.trans.impl;

import com.colorlight.cloud.gateway.api.exception.ReflexException;
import com.colorlight.cloud.gateway.api.message.constraint.basics.object.Trans;
import com.colorlight.cloud.gateway.api.message.interceptor.trans.TransFromProtoInterceptor;
import com.google.protobuf.MessageOrBuilder;

import java.lang.reflect.*;
import java.util.Objects;

/**
 * @author Demon
 * @date 25/12/2023 下午1:47
 */
public class ObjectTransFromProtoInterceptor implements TransFromProtoInterceptor {
	private static final String PROTO_TO_OBJECT = "formProto";
	
	@Override
	public Boolean isInterceptor(Class<?> aClass) {
		return Trans.class.isAssignableFrom(aClass);
	}
	
	@Override
	public void addAttribute(Object transObject, Object value, Class<?> inputClass, String methodName) {
		
		Object o = protoConversionObject(inputClass, value);
		Method method;
		try {
			method = transObject.getClass().getMethod(methodName, inputClass);
		} catch (NoSuchMethodException e) {
			throw new ReflexException("目标枚举类型不存在这个方法");
		}
		try {
			method.invoke(transObject, o);
		} catch (IllegalAccessException | InvocationTargetException e) {
			throw new ReflexException("目标枚举类型方法调用失败");
		}
	}
	
	/**
	 * 根据 类型 转化属性
	 *
	 * <p>1.创建枚举对象 2.获取目标属性 3.反射注入枚举属性
	 *
	 * @param transClass  目标类型
	 * @param sourceValue 原始值
	 * @return 目标属性
	 * @author Demon
	 * @date 29/12/2023/上午10:05
	 */
	public Object protoConversionObject(Class<?> transClass, Object sourceValue) {
		// 创建枚举对象
		Class<? extends Trans<?, ?>> targetClass = (Class<? extends Trans<?, ?>>) transClass;
		Trans<?, ?> trans = builderNilTargetObject(targetClass);
		return setTransObjectValue(PROTO_TO_OBJECT, trans, sourceValue);
	}
	
	/**
	 * 反射注入
	 *
	 * @param methodName 注入方法名 固定为 ： formProto
	 * @param object     通过反射构建的对象
	 * @param value      入参
	 * @return 目标对象
	 * @author Demon
	 * @date 28/12/2023/下午3:30
	 */
	private Object setTransObjectValue(String methodName, Object object, Object value) {
		if(Objects.isNull(value)){
			return null;
		}
		Method method = null;
		try {
			method = object.getClass().getMethod(methodName, MessageOrBuilder.class);
		} catch (NoSuchMethodException e) {
			throw new ReflexException(
					"Object反射获取Tran方法失败\nMethodName:"
							+ methodName
							+ "\nTargetType"
							+ object.getClass()
							+ "\nSource:"
							+ value.getClass()
							+ "\n"
							+ e);
		}
		try {
			return method.invoke(object, value);
		} catch (IllegalAccessException | InvocationTargetException e) {
			throw new ReflexException("Object反射获取调用方法失败\nMethodName:"
					+ methodName
					+ "\nTargetType"
					+ object.getClass()
					+ "\nSource:"
					+ value.getClass()
					+ "\n"
					+ e);
		}
	}
	
	/**
	 * 通过反射创建实体对象
	 *
	 * @param tranClass 需要构建对象类型
	 * @return 目标对象
	 * @author Demon
	 * @date 29/12/2023/上午11:18
	 */
	private Trans<?, ?> builderNilTargetObject(Class<? extends Trans<?, ?>> tranClass) {
		// 通过反射创建对象
		Trans<?, ? extends MessageOrBuilder> trans = null;
		try {
			Constructor<? extends Trans<?, ?>> declaredConstructor = tranClass.getDeclaredConstructor();
			// 构造方法公有化
			declaredConstructor.setAccessible(true);
			trans = declaredConstructor.newInstance();
			
		} catch (InstantiationException
				| IllegalAccessException
				| InvocationTargetException
				| NoSuchMethodException instantiationException) {
			instantiationException.printStackTrace();
		}
		if (Objects.isNull(trans)) {
			throw new ReflexException("");
		}
		return trans;
	}
}
